package com.yanqu.road.server.manger;

import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.servergroup.ICrossServerGroup;
import com.yanqu.road.entity.union.cross.CrossUnionServerGroup;
import com.yanqu.road.logic.bussiness.servercenter.ServerBussiness;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.manger.plugin.ManagerReloadListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossUnionServerGroupMgr extends TempMgr {

    private static final Logger logger = LogManager.getLogger(CrossUnionServerGroupMgr.class.getName());

    private static Map<Integer, Map<Integer, CrossUnionServerGroup>> channelServerGroupMap;

    private static Map<Integer, CrossUnionServerGroup> serverGroupMap;

    private static List<ManagerReloadListener> managerReloadListener = new ArrayList<>();

    private static ICrossServerGroupAccess crossServerGroupAccess;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        reloadServerGroup();
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    public static void reloadServerGroup(){
        Map<Integer, Map<Integer, CrossUnionServerGroup>> tempChannelServerGroupMap = new ConcurrentHashMap<>();
        Map<Integer, CrossUnionServerGroup> tempServerGroupMap = new ConcurrentHashMap<>();
        ServerBussiness.getCrossUnionServerGroupMap(tempChannelServerGroupMap, tempServerGroupMap);
        channelServerGroupMap = tempChannelServerGroupMap;
        serverGroupMap = tempServerGroupMap;
        getLogger().info("CrossUnionServerGroupMgr reload");
        notifyReload();
    }

    private static void notifyReload(){
        for (ManagerReloadListener listener : managerReloadListener) {
            listener.notifyReload();
        }
    }

    public static void addReloadListener(ManagerReloadListener reloadListener){
        managerReloadListener.add(reloadListener);
    }

    public static Map<Integer, CrossUnionServerGroup> getServerGroupMap(int channelId){
        return channelServerGroupMap.get(channelId);
    }

    public static List<CrossUnionServerGroup> getServerGroupList(int channelId){
        Map<Integer, CrossUnionServerGroup> dataMap = getServerGroupMap(channelId);
        if(null != dataMap){
            return new ArrayList<>(dataMap.values());
        }
        return new ArrayList<>();
    }

    public static CrossUnionServerGroup getServerGroup(int groupId){
        return serverGroupMap.get(groupId);
    }

    public static int getGroupIdByServerId(long serverId){
        int groupId = (int)serverId;
        CrossUnionServerGroup serverGroup = getServerGroupByServerId(serverId);
        if(null != serverGroup && serverGroup.getState() == 1){
            groupId = serverGroup.getGroupId();
        }
        return groupId;
    }

    public static CrossUnionServerGroup getServerGroupByServerId(long serverId){
        CrossUnionServerGroup serverGroup = null;
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if(null == serverInfo){
            for(CrossUnionServerGroup tempGroup : serverGroupMap.values()){
                if(tempGroup.getServerList().contains(serverId)){
                    serverGroup = tempGroup;
                    break;
                }
            }
        }else {
            Map<Integer, CrossUnionServerGroup> dataMap = getServerGroupMap(serverInfo.getChannelId());
            if(null != dataMap){
                for(CrossUnionServerGroup tempGroup : dataMap.values()){
                    if(tempGroup.getServerList().contains(serverId)){
                        serverGroup = tempGroup;
                        break;
                    }
                }
            }
        }
        return serverGroup;
    }

    public static Set<Long> getGroupServer(int groupId){
        Set<Long> serverSet = new HashSet<>();
        CrossUnionServerGroup serverGroup = getServerGroup(groupId);
        if(serverGroup == null || serverGroup.getState() == 0){
            serverSet.add((long)groupId);
        }else{
            serverSet.addAll(serverGroup.getServerList());
        }
        return serverSet;
    }

    public static ICrossServerGroupAccess initServerGroupAccess(){

        crossServerGroupAccess = new ICrossServerGroupAccess() {
            @Override
            public int getGroupIdByServerId(long serverId) {
                return CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
            }

            @Override
            public ICrossServerGroup getServerGroup(int groupId) {
                return CrossUnionServerGroupMgr.getServerGroup(groupId);
            }

            @Override
            public ICrossServerGroup getServerGroupByServerId(long serverId) {
                return CrossUnionServerGroupMgr.getServerGroupByServerId(serverId);
            }

            @Override
            public Set<Long> getGroupServer(int groupId) {
                return CrossUnionServerGroupMgr.getGroupServer(groupId);
            }

            @Override
            public void reloadServerGroup() {
                CrossUnionServerGroupMgr.reloadServerGroup();
            }

        };

        return crossServerGroupAccess;
    }

    /**
     * 描述：获取跨服分组服务器数量
     * 作者：zrq
     * 时间：2023/4/4
     * 参数：
     * 返回值：
     **/
    public static int getGroupServerCountByServerId(long serverId) {
        CrossUnionServerGroup serverGroup = getServerGroupByServerId(serverId);
        if (null != serverGroup && serverGroup.getState() == 1) {
            return serverGroup.getServerList().size();
        }
        return 1;
    }

    /**
     * 根据区服数量获取所有服务器 k:serverNum
     */
    public static Map<Integer, List<CrossUnionServerGroup>> getServerListMapByServerNum(int channelId) {
        Map<Integer, List<CrossUnionServerGroup>> serverNumMap = new ConcurrentHashMap<>();
        for (CrossUnionServerGroup serverGroup : serverGroupMap.values()) {
            if (serverGroup.getState() != 1) {
                continue;
            }
            if (serverGroup.getChannelId() != channelId){
                continue;
            }
            int serverNum = serverGroup.getServerList().size();
            List<CrossUnionServerGroup> allServerList = serverNumMap.get(serverNum);
            if (null == allServerList) {
                allServerList = new ArrayList<>();
                serverNumMap.put(serverNum, allServerList);
            }
            allServerList.add(serverGroup);
        }
        return serverNumMap;
    }

    /**
     * 根据区服数量获取所有服务器 k:serverNum
     */
    public static List<CrossUnionServerGroup> getServerListMapByServerNum(Set<Integer> serverNumSet, int serverNumNeed) {
        List<CrossUnionServerGroup> serverGroupList = new ArrayList<>();
        for (CrossUnionServerGroup serverGroup : serverGroupMap.values()) {
            if (serverGroup.getState() != 1) {
                continue;
            }
            int serverNum = serverGroup.getServerList().size();
            if (!serverNumSet.contains(serverNum)){
                continue;
            }
            if (serverNum< serverNumNeed){
                continue;
            }
            serverGroupList.add(serverGroup);
        }
        return serverGroupList;
    }
}
